package steed.util.system;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

import steed.domain.system.Config;
import steed.exception.runtime.system.FrameworkException;
import steed.hibernatemaster.util.DaoUtil;
import steed.hibernatemaster.util.DaoUtil.ImmediatelyTransactionData;
import steed.util.base.BaseUtil;
import steed.util.base.DateUtil;



/**
 * @author 战马
 *
 */
public class FlowUtil {
	private FlowUtil(){}
	
	/**
	 * 
	 * @param key 流水号键(不同键生成的流水号互不影响)
	 * @param flowLength 流水号长度
	 * @param includeTimestamp 流水号是否包含日期
	 * @return
	 */
	public static String getFlowString(String key,
			int flowLength,boolean includeTimestamp){
		Lock lock = SynchronizedUtil.getLock("steed.util.system.FlowUtil.getFlowString(String, int, boolean)"+key);
		try {
			lock.tryLock(100, TimeUnit.SECONDS);
			ImmediatelyTransactionData immediatelyTransactionBegin = DaoUtil.immediatelyTransactionBegin();
			Config config2 = DaoUtil.get(Config.class, key);
			if (config2 == null) {
				config2 = new Config(key, "201603140");
				config2.setType(3);
				config2.save();
			}
			Config config = updateFlow(config2,includeTimestamp);
			String flow = config.getValue().substring(8);
			for (int i = flow.length(); i < flowLength; i++) {
				flow = "0"+flow;
			}
			if (includeTimestamp) {
				flow = config.getValue().substring(0, 8)+flow;
			}
			DaoUtil.managTransaction();
			DaoUtil.immediatelyTransactionEnd(immediatelyTransactionBegin);
			return flow;
		} catch (Exception e) {
			BaseUtil.getLogger().warn("生成流水号出错!",e);
		}finally {
			lock.unlock();
		}
		return UUID.randomUUID().toString();
	}

	private static Config updateFlow(Config config,boolean includeTimestamp) {
		String dateString = config.getValue().substring(0, 8);
		Date today = DateUtil.getToday();
		String flow = config.getValue().substring(8);
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		Date lastUpdateDate;
		try {
			lastUpdateDate = dateFormat.parse(dateString);
		} catch (ParseException e) {
			throw new FrameworkException("表config中主键为"+config.getKee()+
					"的值"+dateString+"不符合yyyyMMdd日期格式！！");
		}
		if (lastUpdateDate.getTime() < today.getTime()) {
			if (includeTimestamp) {
				config.setValue(dateFormat.format(today)+1);
			}else {
				config.setValue(dateFormat.format(today)+(Long.parseLong(flow)+1));
			}
		}else {
			config.setValue(dateString+(Long.parseLong(flow)+1));
		}
		config.update();
		return config;
	} 
}
